using System;
using System.Collections.Generic;
using System.Xml.Linq;
using SpecMaker.Core.Interfaces;
using System.Linq;
namespace SpecMaker.Core
{
    public class NUnitXmlReporter :IReportFactory
    {
        private readonly IIOWriter _filewriter;

        public NUnitXmlReporter(IIOWriter filewriter)
        {
            _filewriter = filewriter;
        }

        public void FromSpecContainers(SpecResult[] specs)
        {
           
           _filewriter.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>");
            int total = TotalSpecs(specs, x => true);
            int failure = TotalSpecs(specs,x=>x.Status == RuleStatus.Failed || x.Status== RuleStatus.Error);
            int pending = TotalSpecs(specs, x => x.Status == RuleStatus.Pending);
            _filewriter.WriteLine(String.Format("<test-results name=\"SpecMaker rules\" total=\"{0}\" failures=\"{1}\" not-run=\"{2}\">", total, failure, pending));
            _filewriter.WriteLine("<results>");
            foreach (var spec in specs)
            {
                
                _filewriter.WriteLine(String.Format( "<test-suite name=\"{0}.{1}\" success=\"True\"  asserts=\"0\">", spec.SpecObject, spec.Context));
                _filewriter.WriteLine("<results>");
                foreach (var result in spec.Results)
                {
                    string issuccess = "True";
                    if (result.Status != RuleStatus.Passed)
                        issuccess = "False";
                    _filewriter.WriteLine(String.Format("<test-case name=\"{0}\" executed=\"True\" success=\"{1}\" time=\"0.000\" asserts=\"1\" />",result.Description, issuccess));
                }

                _filewriter.WriteLine("</results>");
                _filewriter.WriteLine("</test-suite>");
            }
            _filewriter.WriteLine("</results>");
            _filewriter.WriteLine("</test-results>");
           
        }
         private int TotalSpecs(IEnumerable<SpecResult> specs, Func<RuleResult,bool> matches)
         {
             int count = 0;
             foreach (var spec in specs)
             {
                 foreach (var result in spec.Results)
                 {
                     if(matches.Invoke(result))
                     {
                         count += 1;
                     }
                 }
             }
             return count;
         }
    }
}